package com.wb.iec104.analysis;

import com.wb.iec104.factory.AnaFactory;
import com.wb.iec104.factory.DefaultAnaFactoryHandler;
import com.wb.iec104.utils.Util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 遥测信息解析
 *
 * @author cy 2018.01.12
 */
public class TelesignallingIEC104 {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    private static AnaFactory anaFactory = new DefaultAnaFactoryHandler();
    private static DecimalFormat df = new DecimalFormat("#0.000000");

    public static String Bytes2Float_NVA(int low, int high) {
        float fVal;
        int nva = (high << 8) + low;
        // 符号位1位，0为正数，1为负数，后面的为补码表示，
        // 正数的补码和原码相同不需要转换。对于负数,先取反码再加1得到补码的补码，就是原码了。
        int symbol = (high & 0x80);//符号位：0表示正数，1表示负数
        if (symbol == 0x80) {
            fVal = -1 * (((nva ^ 0xffff) + 1) & 0x7fff);//  (nva ^ 0xffff) + 1 :补码的补码  ，取出后面的15位数据乘上-1得到值
        } else {
            fVal = nva;
        }
        //这里的32767值的是一个量纲，一般这个参数是主站和从站商定的
        return df.format(fVal / 32767);
    }

    public static void normalizationNoDqs(int[] infoElement, int num, int tI, int sQ) {
        StringBuilder builder = new StringBuilder();
        Bean bean = null;
            if (sQ == 1) {

                builder.append("遥测信息对象地址");
                int addr = ASDU.infoAddress(infoElement[0], infoElement[1]);
                builder.append("\n");
                for (int i = 0; i < num; i++) {
                    int start = i * 2;
                    int tempAddr = addr + i;

                    String float_data = Bytes2Float_NVA(infoElement[start + 3], infoElement[start + 4]);
                    builder.append("\n");
                    bean = new Bean(tempAddr, sdf.format(new Date()), float_data);
                    anaFactory.handleData(bean);
                }
            } else {
                for (int i = 0; i < num; i++) {
                    builder.append("信息对象");
                    builder.append((i + 1));
                    builder.append("的地址：");
                    builder.append(ASDU.InfoAddress(infoElement[i * 6],
                            infoElement[i * 6 + 1], infoElement[i * 6 + 2]));
                    builder.append("\n");
                    builder.append("归一化值NVA:");
                    builder.append(Util.toHexString(infoElement[i * 6 + 3]));
                    builder.append("\t");
                    builder.append(Util.toHexString(infoElement[i * 6 + 4]));
                    builder.append("\n");
                    builder.append("\n");
                }
            }
    }


    /**
     * 测量值，归一化值
     *
     * @param infoElement
     * @param num
     * @param tI
     * @param sQ
     * @return
     */
    public static void normalization(int[] infoElement, int num, int tI, int sQ) {
        StringBuilder builder = new StringBuilder();
        if (sQ == 1) {

            builder.append("遥测信息对象地址");
            builder.append(ASDU.InfoAddress(infoElement[0], infoElement[1],
                    infoElement[2]));
            builder.append("\n");
            for (int i = 0; i < num; i++) {
                builder.append("信息对象");
                builder.append(i + 1);
                builder.append("归一化值NVA:");
                builder.append(Util.toHexString(infoElement[i * 3 + 3]));
                builder.append("\t");
                builder.append(Util.toHexString(infoElement[i * 3 + 4]));
                builder.append("\n");
                builder.append("品质描述词QDS:");
                builder.append(Util.toHexString(infoElement[i * 3 + 5]));
                builder.append("\n");
            }
        } else {
            for (int i = 0; i < num; i++) {
                builder.append("信息对象");
                builder.append((i + 1));
                builder.append("的地址：");
                builder.append(ASDU.InfoAddress(infoElement[i * 6],
                        infoElement[i * 6 + 1], infoElement[i * 6 + 2]));
                builder.append("\n");
                builder.append("归一化值NVA:");
                builder.append(Util.toHexString(infoElement[i * 6 + 3]));
                builder.append("\t");
                builder.append(Util.toHexString(infoElement[i * 6 + 4]));
                builder.append("\n");
                builder.append("品质描述词QDS:");
                builder.append(Util.toHexString(infoElement[i * 6 + 5]));
                builder.append("\n");
            }
        }

        System.out.println(builder.toString());
    }

    /**
     * 测量值，标度化值
     *
     * @param infoElement
     * @param num
     * @param tI
     * @param sQ
     * @return
     */
    public String standardization(int[] infoElement, int num, int tI, int sQ) {
        String string = "";

        return string;
    }

    /**
     * 测量值，短浮点数
     *
     * @param infoElement
     * @param num
     * @param tI
     * @param sQ
     * @return
     */
    public static void short_float(int[] infoElement, int num, int tI, int sQ) {

        Bean bean = null;
        String timeScale = sdf.format(new Date());
            if (sQ == 1) {
                int addr = ASDU.infoAddress(infoElement[0], infoElement[1], infoElement[2]);
                for (int i = 0; i < num; i++) {
                    String short_data = Util.toHexString(infoElement[i * 5 + 6], true);
                    short_data += Util.toHexString(infoElement[i * 5 + 5], true);
                    short_data += Util.toHexString(infoElement[i * 5 + 4], true);
                    short_data += Util.toHexString(infoElement[i * 5 + 3], true);
                    //把16进制的字节数字转为浮点类型
                    float fdata = Float.intBitsToFloat((int) Long.parseLong(short_data, 16));
                    BigDecimal bigDecimal = new BigDecimal(Double.toString(fdata));
                    int dqs = infoElement[i * 5 + 7];
                    int tempAddr = addr + i;
                    bean = new Bean(tempAddr, dqs, df.format(Double.parseDouble(bigDecimal.toString())), timeScale);
                    anaFactory.handleData(bean);

                }
            } else {
                for (int i = 0; i < num; i++) {
                    int addr = ASDU.infoAddress(infoElement[i * 8],
                            infoElement[i * 8 + 1], infoElement[i * 8 + 2]);
                    String short_data = Util.toHexString(infoElement[i * 8 + 6], true);
                    short_data += Util.toHexString(infoElement[i * 8 + 5], true);
                    short_data += Util.toHexString(infoElement[i * 8 + 4], true);
                    short_data += Util.toHexString(infoElement[i * 8 + 3], true);
                    //把16进制的自己数字转为浮点类型
                    float fdata = Float.intBitsToFloat((int) Long.parseLong(short_data, 16));
                    BigDecimal bigDecimal = new BigDecimal(Double.toString(fdata));
                    int dqs = infoElement[i * 8 + 7];
                    bean = new Bean(addr, dqs, df.format(Double.parseDouble(bigDecimal.toString())), timeScale);
                    anaFactory.handleData(bean);
                }
            }
        }


    /**
     * 解析带时标的测量值  浮点类型
     *
     * @param infoElement
     * @param num
     * @param tI
     * @param sQ
     */
    public static void Time_Point_Short_Flaot(int[] infoElement, int num, int tI, int sQ) {
        //[122, 69, 0, 28, 199, 177, 60, 0, 166, 103, 0, 0, 21, 3, 22, 123, 69, 0, 228, 56, 142, 187, 0, 166, 103, 0, 0, 21, 3, 22]
        Bean bean = null;
        long cost = 0;
            if (sQ == 0) {
                for (int i = 0; i < num; i++) {
                    int size = i * 15;
                    int addr = ASDU.infoAddress(infoElement[size],
                            infoElement[size + 1], infoElement[size + 2]);
                    String short_data = Util.toHexString(infoElement[size + 6], true);
                    short_data += Util.toHexString(infoElement[size + 5], true);
                    short_data += Util.toHexString(infoElement[size + 4], true);
                    short_data += Util.toHexString(infoElement[size + 3], true);
                    float fdata = Float.intBitsToFloat((int) Long.parseLong(short_data, 16));
                    BigDecimal bigDecimal = new BigDecimal(Double.toString(fdata));
                    int dqs = infoElement[size + 7];
                    int time[] = new int[7];
                    size += 8;
                    for (int j = 0; j < 7; j++) {
                        time[j] = infoElement[size + j];
                    }
                    String timeScale = Util.TimeScale(time);
                    if (i == 0) {
                        try {
                            cost = System.currentTimeMillis() - sdf.parse(timeScale).getTime();
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    bean = new Bean(addr, dqs, df.format(Double.parseDouble(bigDecimal.toString())), timeScale, cost);
                    anaFactory.handleData(bean);
                }
            } else {
                int addr = ASDU.infoAddress(infoElement[0], infoElement[1], infoElement[2]);
                //a3 41 00 9a 99 e5 41 00 e8 80 52 10 7e 73 16 00 00 00 00 00
                for (int i = 0; i < num; i++) {
                    int start = (i * 12) + 3;
                    String short_data = Util.toHexString(infoElement[start + 3], true);
                    short_data += Util.toHexString(infoElement[start + 2], true);
                    short_data += Util.toHexString(infoElement[start + 1], true);
                    short_data += Util.toHexString(infoElement[start], true);
                    float fdata = Float.intBitsToFloat((int) Long.parseLong(short_data, 16));
                    BigDecimal bigDecimal = new BigDecimal(Double.toString(fdata));
                    //bigDecimal.setScale(BigDecimal.ROUND_HALF_UP,6);
                    //品质描述  在第8位
                    int dqs = infoElement[start + 4];
                    dqs = (dqs & 0x80) == 0 ? 0 : 1;
                    //解析时间 时间是从第9位开始 到第14位
                    int time[] = new int[7];
                    start += 5;
                    for (int j = 0; j < 7; j++) {
                        time[j] = infoElement[start + j];
                    }
                    String timeScale = Util.TimeScale(time);
                    if (i == 0) {
                        try {
                            cost = System.currentTimeMillis()- sdf.parse(timeScale).getTime();
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                    int tempAddr = addr + i;
                    bean = new Bean(tempAddr, dqs, df.format(Double.parseDouble(bigDecimal.toString())), timeScale, cost);
                    anaFactory.handleData(bean);
                }

            }


    }

}
